const ALLTIME = 60; // 整条航线耗时（秒）
// 巡航类
export default class Cruise {
	constructor(viewer) {
		this.viewer = viewer;
		// 飞机模型地址（注，模型大小控制在5M内，否则会加载不出）
		this.modelUrl = './data/city/s9_drone/scene.gltf';
		// 路径数据是否生成完毕
		this.isLoadData = false;
		// 飞行路径数据
		this.pathCZML = null;
		// 飞行路径DataSource
		this.CzmlDataSource = null;
		// 飞行器对象
		this.flyEntity = null;
		// 中心位置
		this.target = null;
		// 跟随视角
		this.eyeAngle = 'third'; // 默认第三视角
		// 跟随监听函数
		this.setRoamView = this._setRoamViewThird;
		// 当前是否跟随
		this.isFollow = false;
	}

	/* 生成巡航所需数据
    * pointArr:控制点点集
        [[lon, lat, h],[lon, lat, h]]
    * speed:速度（单位s）
    * target:巡航路线中心经纬度，用于控制跟随角度
        [lon, lat]
    */
	loadDataInfo(param) {
		const { pointArr, speed = 10, modelShow = false } = param;

		// 初始化状态
		this.destroyed();
		if (!pointArr || pointArr.length < 2) return;

		// 配置中心位置
		const center = this.getTarget(pointArr);
		this.target = new Cesium.Cartesian3.fromDegrees(...center);

		// 计算路径及时间信息
		const start = new Date();
		const cartographicDegrees = [];
		let time = 0;
		const len = pointArr.length;
		for (let i = 0; i < len; i++) {
			const ponit = pointArr[i];
			cartographicDegrees.push(
				time + i * speed,
				ponit[0],
				ponit[1],
				ponit[2] || 0
			);
			time += speed;
		}
		const end = new Date(start.getTime() + (time - speed) * 1000 * 2);
		const startString = start.toISOString();
		const endString = end.toISOString();
		const timeRange = startString + '/' + endString;

		// 生成所需路径数据并更改状态
		this.pathCZML = [
			{
				id: 'document',
				name: 'CZML Path',
				version: '1.0',
				clock: {
					interval: timeRange,
					currentTime: startString,
					multiplier: 2,
				},
			},
			{
				id: 'path',
				name: 'fly path',
				availability: timeRange,
				path: {
					material: {
						polylineOutline: {
							color: {
								rgba: [255, 0, 255, 255],
							},
							outlineColor: {
								rgba: [0, 255, 255, 255],
							},
							outlineWidth: 5,
							clampToGround: true,
						},
					},
					width: 6,
					leadTime: 0,
					trailTime: 1000,
					resolution: 5,
				},
				model: {
					gltf: this.modelUrl,
					minimumPixelSize: 200,
					maximumScale: 30,
					show: modelShow,
					// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
				},
				orientation: {
					velocityReference: '#position',
				},
				position: {
					// interpolationAlgorithm: 'LINEAR',
					// forwardExtrapolationType: 'HOLD',
					interpolationAlgorithm: 'LAGRANGE',
					interpolationDegree: 1,
					epoch: startString,
					cartographicDegrees,
				},
			},
		];
		this.isLoadData = true;
	}

	// 巡航路线中心经纬度，用于控制跟随角度
	getTarget(pointArr) {
		let lon = 0,
			lat = 0;
		const len = pointArr.length;
		for (let i = 0; i < len; i++) {
			const ponit = pointArr[i];
			lon += ponit[0];
			lat += ponit[1];
		}
		return [lon / len, lat / len];
	}

	// 加载模型并开始飞行(默认飞行不跟踪)
	add(param = {}) {
		const { isFly = true, isFollow = false } = param;
		this.isFollow = isFollow;
		if (this.pathCZML) {
			this.viewer.dataSources
				.add(Cesium.CzmlDataSource.load(this.pathCZML))
				.then((ds) => {
					// 储存相关对象，供后续使用
					this.CzmlDataSource = ds;
					this.flyEntity = ds.entities.getById('path');

					// 路径插值
					// flyEntity.position.setInterpolationOptions({
					//   interpolationDegree: 2,
					//   interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
					// })
				});
			// 开启时钟
			isFly && this.changeFly(true);
			isFollow && this.lookFly(true);
		} else {
			console.error('巡航路径有误！');
		}
	}

	// 控制飞行状态
	changeFly(isFly = false) {
		this.viewer.clock.shouldAnimate = isFly;
	}

	// 巡航跟踪()
	lookFly(isFollow = true) {
		// 用相机跟随模型
		if (isFollow) {
			this.isFollow = true;
			this.viewer.scene.preUpdate.addEventListener(this.setRoamView);
		} else {
			this.isFollow = false;
			this.viewer.scene.preUpdate.removeEventListener(this.setRoamView);
			// lookAt 会锁定视角，需手动解绑
			this.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
		}

		// 也可锁定飞行器
		// this.viewer.trackedEntity = entity
		// entity.viewFrom = new Cesium.Cartesian3(-2000, 0, 2000)
	}

	// 修改当前跟随视角
	changeEyeAngle(eyeAngle) {
		if (this.eyeAngle === eyeAngle) return;
		// 更换当前飞行视角
		this.eyeAngle = eyeAngle === 'third' ? 'third' : 'first';
		// 如当前正在跟随，移除监听函数
		this.isFollow &&
			this.viewer.scene.preUpdate.removeEventListener(this.setRoamView);
		// 更换监听函数
		this.setRoamView =
			eyeAngle === 'third'
				? this._setRoamViewThird
				: this._setRoamViewFirst;
		// 如当前正在跟随，添加新监听函数
		this.isFollow &&
			this.viewer.scene.preUpdate.addEventListener(this.setRoamView);
	}

	// 巡航响应事件(第一视角)
	_setRoamViewFirst = () => {
		if (this.flyEntity) {
			const center = this.flyEntity.position.getValue(
				this.viewer.clock.currentTime
			);
			const ori = this.flyEntity.orientation.getValue(
				this.viewer.clock.currentTime
			);
			let transform = Cesium.Matrix4.fromRotationTranslation(
				Cesium.Matrix3.fromQuaternion(ori),
				center
			); //将偏向角转为3*3矩阵，利用实时点位转为4*4矩阵
			this.viewer.camera.lookAtTransform(
				transform,
				new Cesium.Cartesian3(-2000, 0, 2000)
			); //将相机向后面放一点
			// if (center) {
			// 	const vector = new Cesium.Cartesian3(
			// 		this.target.x - center.x,
			// 		this.target.y - center.y,
			// 		1500
			// 	);
			// 	this.viewer.camera.lookAt(center, vector);
			// }
		}
	};

	// 巡航响应事件(第三视角)
	_setRoamViewThird = () => {
		if (this.flyEntity) {
			const center = this.flyEntity.position.getValue(
				this.viewer.clock.currentTime
			);
			if (center) {
				const vector = new Cesium.Cartesian3(
					this.target.x - center.x,
					this.target.y - center.y,
					1500
				);
				this.viewer.camera.lookAt(center, vector);
			}
		}
	};

	// 移除但未销毁，路径数据还在，可继续add加载
	remove() {
		if (this.CzmlDataSource) {
			this.viewer.dataSources.remove(this.CzmlDataSource, true);
			this.CzmlDataSource = null;
			this.flyEntity = null;
		}
	}

	// 彻底销毁，包括路径数据，需要loadDataInfo生成路径后方可add加载
	destroyed() {
		this.remove();
		this.isLoadData = false;
		this.pathCZML = null;
	}
}
